package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.service.AlbumInfoService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.rabbit.constant.MqConst;
import com.atguigu.tingshu.common.rabbit.service.RabbitService;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.query.album.AlbumInfoQuery;
import com.atguigu.tingshu.vo.album.AlbumAttributeValueVo;
import com.atguigu.tingshu.vo.album.AlbumInfoVo;
import com.atguigu.tingshu.vo.album.AlbumListVo;
import com.atguigu.tingshu.vo.album.AlbumStatVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Random;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo> implements AlbumInfoService {

    //用到哪些表注入对应的mapper
    @Autowired
    private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;
    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private RabbitService rabbitService;


    //	如果是批量保存： 借助ServiceImpl 实现类： this.saveBatch();

    @Override
    public AlbumStatVo getAlbumStatVo(Long albumId) {
        //	调用mapper 层方法;
        return albumInfoMapper.selectAlbumStatVo(albumId);
    }

    /**
     * 获取用户专辑列表
     *
     * @param albumListVoPage
     * @param albumInfoQuery
     * @return
     */
    @Override
    public IPage<AlbumListVo> findUserAlbumPage(Page<AlbumListVo> albumListVoPage, AlbumInfoQuery albumInfoQuery) {
        // 调用mapper层的方法
        // 	查询数据有专辑基本信息+专辑统计信息; album_info; album_stat;
        return albumInfoMapper.selectUserAlbumPage(albumListVoPage, albumInfoQuery);
    }

    /**
     * 查询用户专辑列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<AlbumInfo> findUserAllAlbumList(Long userId) {
        //	select * from album_info where user_id = 1;
        //	select id, album_title from album_info where user_id = 1;
        //	List<AlbumInfo> albumInfoList = albumInfoMapper.selectList(new LambdaQueryWrapper<AlbumInfo>().eq(AlbumInfo::getUserId, userId)
        //                                                            	.select(AlbumInfo::getId, AlbumInfo::getAlbumTitle).orderByDesc(AlbumInfo::getId));
        //	前端应该传递pageNo,pageSize;//因为前端没写，所以在这里写死
        //创建了一个分页对象 albumInfoPage，初始设置为第1页，每页显示10条记录
        Page<AlbumInfo> albumInfoPage = new Page<>(1,10);
        Page<AlbumInfo> infoPage = albumInfoMapper.selectPage(albumInfoPage, new LambdaQueryWrapper<AlbumInfo>()
                                                    .eq(AlbumInfo::getUserId, userId)
                                                    .select(AlbumInfo::getId, AlbumInfo::getAlbumTitle)
                                                    .orderByDesc(AlbumInfo::getId));//按 id 字段降序排序。
        //	建立索引：album_title;
        return infoPage.getRecords();
    }

    /**
     * 更新专辑信息
     *
     * @param albumId
     * @param albumInfoVo
     */
    @Override
    public void updateAlbumInfo(Long albumId, AlbumInfoVo albumInfoVo) {
        //创建一个新的 AlbumInfo 对象，用于存储从 AlbumInfoVo 对象中复制的属性值。
        AlbumInfo albumInfo = new AlbumInfo();
        //用于将 albumInfoVo 对象的属性值复制到 albumInfo 对象中
        BeanUtils.copyProperties(albumInfoVo, albumInfo);
        //设置 albumInfo 对象的 id 属性为传入的 albumId
        //确保更新操作针对正确的专辑记录
        //如果 albumId 为 123，则 albumInfo 对象的 id 属性会被设置为 123。
        albumInfo.setId(albumId);
        //调用 albumInfoMapper 的 updateById 方法，根据 albumInfo 对象的 id 属性更新数据库中的记录
        //将 albumInfo 对象中的属性值更新到数据库中，对应 album_id 为 albumId 的记录。
        albumInfoMapper.updateById(albumInfo);
        //	album_attribute_value 先删除，再新增!
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
        //	album_attribute_value 添加数据！
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList();
        //	判断
        if (!CollectionUtils.isEmpty(albumAttributeValueVoList)){
            for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) {
                //	创建对象
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue();
                //	属性拷贝：
                BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue);
                //	因为53行执行了insert 方法。所以通过type = IdType.AUTO 属性配置，就能够获取到主键自增的id
                albumAttributeValue.setAlbumId(albumInfo.getId());
                //	保存数据：insert into album_attribute_value values(?,?,?); insert into album_attribute_value values(?,?,?);
                //	insert into album_attribute_value values (?,?,?) (?,?,?) (?,?,?) mybatis-plus 的批量插入！
                albumAttributeValueMapper.insert(albumAttributeValue);
            }
        }
        //	判断：
        if ("1".equals(albumInfoVo.getIsOpen())){
            //	上架 需要专辑Id;
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER,albumId);
        } else {
            //	下架
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_LOWER,albumId);
        }
    }

    /**
     * 根据id获取专辑对象数据
     *
     * @param albumId
     * @return
     */
    @Override
    public AlbumInfo getAlbumInfo(Long albumId) {
        //this 关键字表示当前对象实例。
        // 在 AlbumInfoServiceImpl 类中，this 表示当前的 AlbumInfoServiceImpl 实例。
        AlbumInfo albumInfo = this.getById(albumId);
        if (albumInfo != null) {
            //selectList 方法: 调用 albumAttributeValueMapper 的 selectList 方法，根据条件查询 AlbumAttributeValue 对象列表。
            //setAlbumAttributeValueVoList 方法: 将查询到的 AlbumAttributeValue 对象列表设置到 albumInfo 对象的 albumAttributeValueVoList 属性中。
            albumInfo.setAlbumAttributeValueVoList(albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId)));
        }
        return albumInfo;
    }

    /**
     * 删除专辑
     *
     * @param albumId
     */
    @Override
    //异常处理: 通过 rollbackFor 属性指定哪些异常会导致事务回滚。
    //Exception.class: 指定所有类型的异常（包括 RuntimeException 和 CheckedException）都会导致事务回滚。
    @Transactional(rollbackFor = Exception.class)
    public void removeAlbumInfo(Long albumId) {
        //album_info
        albumInfoMapper.deleteById(albumId);
        //album_attribute_value
        //	delete from album_attribute_value where album_id = ? and is_delete=0; 物理删除;
        //	update album_attribute_value set is_delete=1 where album_id = ? and is_delete=0; 逻辑删除
//需要考虑逻辑删除问题! 因为已经在BaseEntity添加@TableLogic,以后所有的接口都具备了逻辑删除能力!!!  即使用delete，也是逻辑删除
        albumAttributeValueMapper.delete(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumId));
        //album_stat
        albumStatMapper.delete(new LambdaQueryWrapper<AlbumStat>().eq(AlbumStat::getAlbumId, albumId));
    }

    /**
     * 保存专辑信息
     * //	如果是批量保存： 借助ServiceImpl 实现类： this.saveBatch();
     * @param albumInfo
     */
    @Override
    @Transactional(rollbackFor = Exception.class) // 出现异常时，三张表同时回滚
    public void saveAlbumInfo(AlbumInfoVo albumInfoVo, Long userId) {
        // 保存专辑信息涉及到这三张表：album_info、album_attribute_value、album_stat
        // 插入数据时，三张表要同时成功或同时失败，因此需要加本地事务

        // 处理 album_info 表 【userId; tracks_for_free; status这三个字段没有】
        AlbumInfo albumInfo = new AlbumInfo(); // 创建专辑信息对象
        //	属性赋值; 属性拷贝 - 属性一致的；将属性数据平移！
        BeanUtils.copyProperties(albumInfoVo, albumInfo); // 将传入的专辑信息VO复制到专辑信息对象
        //	userId; tracks_for_free免费试听集数; status
        albumInfo.setUserId(userId); // 设置用户ID
        //	免费试听集数：
        //	判断当前专辑的类型;
        // 如果不是免费专辑，说明付费专辑: 都应该有试听集数;
        if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
            albumInfo.setTracksForFree(5); // 设置前5首歌曲免费
        }
        albumInfo.setStatus(SystemConstant.ALBUM_STATUS_PASS); // 设置专辑状态为通过审核
        albumInfoMapper.insert(albumInfo); // 插入专辑信息到数据库

        // 处理 album_attribute_value 表
        List<AlbumAttributeValueVo> albumAttributeValueVoList = albumInfoVo.getAlbumAttributeValueVoList(); // 获取专辑属性值列表
        //	判断
        if (!CollectionUtils.isEmpty(albumAttributeValueVoList)) { // 如果专辑属性值列表不为空
            for (AlbumAttributeValueVo albumAttributeValueVo : albumAttributeValueVoList) { // 遍历专辑属性值列表
                //	创建对象
                AlbumAttributeValue albumAttributeValue = new AlbumAttributeValue(); // 创建专辑属性值对象
                //	属性拷贝：
                BeanUtils.copyProperties(albumAttributeValueVo, albumAttributeValue); // 将传入的专辑属性值VO复制到专辑属性值对象
                //	因为53行执行了insert 方法。所以通过type = IdType.AUTO 属性配置，就能够获取到主键自增的id
                albumAttributeValue.setAlbumId(albumInfo.getId()); // 设置专辑ID
                //	保存数据：insert into album_attribute_value values(?,?,?); insert into album_attribute_value values(?,?,?);
                //	insert into album_attribute_value values (?,?,?) (?,?,?) (?,?,?) mybatis-plus 的批量插入！
                albumAttributeValueMapper.insert(albumAttributeValue); // 插入专辑属性值到数据库
            }
        }

        // 处理 album_stat 表
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_PLAY); // 保存播放统计信息
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_SUBSCRIBE); // 保存订阅统计信息
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_BROWSE); // 保存浏览统计信息
        this.saveAlbumStat(albumInfo.getId(), SystemConstant.ALBUM_STAT_COMMENT); // 保存评论统计信息

        if ("1".equals(albumInfoVo.getIsOpen())){
            //	上架 需要专辑Id;
            rabbitService.sendMessage(MqConst.EXCHANGE_ALBUM,MqConst.ROUTING_ALBUM_UPPER,albumInfo.getId());
        }
    }

    public void saveAlbumStat(Long albumId, String statPlay) {
        // 保存专辑统计信息
        AlbumStat albumStat = new AlbumStat(); // 创建专辑统计对象
        albumStat.setAlbumId(albumId); // 设置专辑ID
        albumStat.setStatType(statPlay); // 设置统计类型
        albumStat.setStatNum(new Random().nextInt(10000000)); // 设置随机统计数值
        albumStatMapper.insert(albumStat); // 插入专辑统计信息到数据库
    }
}

